import java.util.ArrayList;
import java.util.regex.Pattern;
import java.io.BufferedReader;
import java.util.TreeSet;
import java.io.FileReader;
import java.util.Set;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Collection;

/**
 * @(#) TaskReader.java
 */
public class TaskReader {
	private TaskUtil util = new TaskUtil();
	
	public Collection readChartFromFile( String fileName ) {
		Collection<Task> tasks = new ArrayList<Task>();
		HashMap<String,Collection<String>> preceedingTasks = new HashMap<String,Collection<String>>();
		
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(fileName));
			String line;

			while ((line = br.readLine()) != null) {
				String[] elements = line.split(",");
				
				if(elements.length < 2) {
					util.showErrorAndExit("Error in line: " + line);
				}
				
				String idTrimmed = elements[0].trim();
								
				if(isNotAlphaNumeric(idTrimmed)) {
					util.showErrorAndExit("Non alphanumeric character in: " + idTrimmed);
				}
				
				Integer duration = null;
				try {
					duration = Integer.parseInt(elements[1].trim());
				} catch (NumberFormatException e) {
					util.showErrorAndExit("Error parsing duration: " + elements[1].trim());
				}
				
				Task newTask = new Task(idTrimmed, duration);
				
				if(isDuplicate(newTask, tasks)) {
					util.showErrorAndExit("Duplicate taskId: " + idTrimmed);
				}
				tasks.add(newTask);
				
				if(elements.length > 2) {
					preceedingTasks.put(idTrimmed, new ArrayList<String>());
					
					for(int i = 2; i < elements.length; i++) {
						String preceedingTaskId = elements[i].trim();
						if(isNotAlphaNumeric(preceedingTaskId)) {
							util.showErrorAndExit("Non alphanumeric character in: " + preceedingTaskId);
						}
						preceedingTasks.get(idTrimmed).add(preceedingTaskId);
					}
				}
			}
			
			br.close();
		} catch (FileNotFoundException e) {
			util.showErrorAndExit("Did not find file: " + fileName);			
		} catch (IOException e) {
			util.showErrorAndExit("Error reading file: " + fileName);
		}
		
		addPreceedingTasks(tasks, preceedingTasks);

		return tasks;
	}

	private void addPreceedingTasks( Collection<Task> tasks, HashMap<String, Collection<String>> preceedingTasks ) {
		
		for(String taskId : preceedingTasks.keySet()) {
			Task task = util.findTaskById(taskId, tasks);
			
			if(task == null) {
				util.showErrorAndExit("Cannot find task with id: " + taskId);
			}
			
			for(String preceedingTaskId : preceedingTasks.get(taskId)) {
				Task preceedingTask = util.findTaskById(preceedingTaskId, tasks);
				task.addPredecessor(preceedingTask);
				preceedingTask.addSuccessor(task);
			}
		}
	}

	private boolean isDuplicate( Task newTask, Collection<Task> tasks ) {
		for(Task task : tasks) {
			if(task.getTaskId().equals(newTask.getTaskId())) {
				return true;
			}
		}
		return false;
	}

	private boolean isNotAlphaNumeric( String name ) {
		Pattern p = Pattern.compile("[^a-zA-Z0-9]");
		return p.matcher(name).find();
	}	
}
